﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace UtilLib
{
    /// <summary>
    /// 权重筛选器
    /// </summary>
    public partial class Weighted<T>
    {
        /// <summary>
        /// 
        /// </summary>
        public List<WeightedItem<T>> Items = new List<WeightedItem<T>>();
        /// <summary>
        /// 是否移除权重0的元素
        /// </summary>
        public bool RemoveZeroWeightItems = true;

        /// <summary>
        /// 累计权重集
        /// </summary>
        [JsonIgnore]
        public int[] CumulativeWeights = Array.Empty<int>();

        /// <summary>
        /// 是否是已经添加过的权重值
        /// </summary>
        public bool _isAddedCumulativeWeights;

        /// <summary>
        /// dict:k是ID或者其他什么, v是权重
        /// </summary>
        /// <param name="dict"></param>
        /// <param name="RemoveZeroWeight"></param>
        public Weighted(Dictionary<T, int> dict, bool RemoveZeroWeight = true)
        {
            RemoveZeroWeightItems = RemoveZeroWeight;
            foreach (var kvp in dict)
            {
                var item = new WeightedItem<T>(kvp.Key, kvp.Value);
                Add(item);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="listItem"></param>
        /// <param name="listWeight"></param>
        /// <param name="RemoveZeroWeight"></param>
        public Weighted(List<T> listItem, List<int> listWeight, bool RemoveZeroWeight = true)
        {
            RemoveZeroWeightItems = RemoveZeroWeight;
            for (int i = 0; i < Math.Min(listItem.Count, listWeight.Count); i++)
            {
                var item = new WeightedItem<T>(listItem[i], listWeight[i]);
                Add(item);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="items"></param>
        /// <param name="RemoveZeroWeight"></param>
        public Weighted(List<WeightedItem<T>> items, bool RemoveZeroWeight = true)
        {
            RemoveZeroWeightItems = RemoveZeroWeight;
            Add(items);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="items"></param>
        /// <param name="RemoveZeroWeight"></param>
        public Weighted(IEnumerable<WeightedItem<T>> items, bool RemoveZeroWeight = true)
        {
            RemoveZeroWeightItems = RemoveZeroWeight;
            Add(items);
        }

        /// <summary>
        /// 添加元素
        /// </summary>
        /// <param name="item"></param>
        public void Add(WeightedItem<T> item)
        {
            if (item.Weight <= 0)
            {
                if (RemoveZeroWeightItems)
                {
                   return;
                }
            }
            _isAddedCumulativeWeights = true;
            Items.Add(item);
        }

        /// <summary>
        /// 批量添加元素
        /// </summary>
        /// <param name="items"></param>
        public void Add(IEnumerable<WeightedItem<T>> items)
        {
            foreach (var item in items)
            {
                Add(item);
            }
        }

        /// <summary>
        /// 添加元素
        /// </summary>
        /// <param name="item"></param>
        /// <param name="weight"></param>
        public void Add(T item, int weight)
        {
            Add(new WeightedItem<T>(item, weight));
        }

        /// <summary>
        /// 移除元素
        /// </summary>
        /// <param name="item"></param>
        public void Remove(WeightedItem<T> item)
        {
            _isAddedCumulativeWeights = true;
            Items.Remove(item);
        }

        /// <summary>
        /// 计算累计权重
        /// </summary>
        private void CalculateCumulativeWeights()
        {
            if (!_isAddedCumulativeWeights) //如果没有被添加，则跳过
            {
                return;
            }

            _isAddedCumulativeWeights = false;
            CumulativeWeights = GetCumulativeWeights(Items);
        }

        /// <summary>
        /// 计算累计权重
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public static int[] GetCumulativeWeights(List<WeightedItem<T>> items)
        {
            int totalWeight = 0;
            int index = 0;
            var results = new int[items.Count + 1];

            foreach (var item in items)
            {
                totalWeight += item.Weight;
                results[index] = totalWeight;
                index++;
            }

            return results;
        }
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <returns></returns>
        //public IEnumerator<T> GetEnumerator()
        //{
        //    return Items.GetEnumerator() as IEnumerator<T>;
        //}
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <returns></returns>
        //IEnumerator IEnumerable.GetEnumerator()
        //{
        //    return GetEnumerator();
        //}
    }
}
